home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Compilers⁄Interps / kevoSource / recompile.c < prev    next >
Text File  |  1993-03-13  |  7KB  |  211 lines

  1. /* Kevo -- a prototype-based object-oriented language */
  2. /* (c) Antero Taivalsaari 1991-1993                   */
  3. /* Some parts (c) Antero Taivalsaari 1986-1988           */
  4. /* recompile.c: Recompiler internals                    */
  5.  
  6. #include "global.h"
  7.  
  8. /*------------------------------------------------------------------------*/
  9. /* These operations automatically rebind all the early bound references   */
  10. /* within an object when properties are CUT/COPY/PASTEd or redefined.      */
  11.  
  12. /* rebind(): needed internally in the subsequent recompilation operations */
  13.  
  14. LIST* oldProps;
  15. LIST* newProps;
  16.  
  17. void rebind(newObjectPtr, origObject, offset, target)
  18. OBJECT** newObjectPtr;
  19. OBJECT*  origObject;
  20. int      offset;
  21. OBJECT*  target;
  22. {
  23.     /* Duplicate the property (only once, however) */
  24.     if (!*newObjectPtr) {
  25.         *newObjectPtr = copyObject(origObject);
  26.  
  27.         /* Add the recompilation information to the property lists */
  28.         addToList(oldProps, origObject);
  29.         addToList(newProps, *newObjectPtr);
  30.     }
  31.                 
  32.     /* Change the reference in the duplicate to point to the new property */
  33.     *((int*)(*newObjectPtr)->mfa + offset) = (int)target;
  34. }
  35.  
  36.  
  37. /*  recompileProperty(): starting from a pair, rebind all the references to 
  38.     the given old property to the current property. 
  39.  
  40.     This operation should be invoked when a property (normally a method)
  41.     is redefined.
  42. */
  43. void recompileProperty(changedPair, oldProperty)
  44. PAIR* changedPair;
  45. OBJECT* oldProperty;
  46. {
  47.   PAIR* thisPair = changedPair->sfa;
  48.   /* 
  49.       Since each rebound property will cause a propagated effect 
  50.       (that property will have to be subsequently rebound too),
  51.       we store the corresponding properties in dynamically growing 
  52.     lists.
  53.   */
  54.   oldProps = createList();
  55.   newProps = createList();
  56.   
  57.     addToList(oldProps, oldProperty);
  58.     addToList(newProps, changedPair->ofa);
  59.  
  60.     /* Walk through all the properties starting from the successor of 'changedPair' */
  61.     while (thisPair) {
  62.         OBJECT* thisObject = thisPair->ofa;
  63.         STORE*    store = thisObject->mfa;
  64.         int     size  = thisObject->sfa;
  65.         OBJECT* newObject = NIL;
  66.         int     offset;
  67.         
  68.         /* Walk through all the slots in the current property */
  69.         for (offset = 0; offset < size; offset++) {
  70.             OBJECT* refObject = (OBJECT*)*((int*)store + offset);
  71.             int     index;
  72.             
  73.             /* Check if the referred property has been redefined */
  74.             if (index = findInList(oldProps, refObject)) 
  75.                 rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
  76.         }
  77.  
  78.         /* If the property was redefined, change the pair to refer to it */
  79.         if (newObject) {
  80.             thisPair->ofa = newObject;
  81.             fprintf(confile, "   Method '%s' recompiled.\n", thisPair->nfa);
  82.         }
  83.         
  84.         thisPair = thisPair->sfa;
  85.     }
  86.     
  87.     deleteList(oldProps);
  88.     deleteList(newProps);
  89. }
  90.  
  91.  
  92. /* This operation is used internally to find the previous property */
  93. /* with the given name starting from an arbitrary pair in a context */
  94.  
  95. PAIR* traverseThread(thePair, string)
  96. PAIR* thePair;
  97. char* string;
  98. {
  99.   int      thread = hash(string);
  100.   PAIR*       prevPair;
  101.   PAIR*       succPair;
  102.   PAIR*    prevInThread;
  103.   PAIR*       succInThread;
  104.  
  105.     /* Use 'findSurroundings' to save efforts (is not the fastest possible, though) */
  106.     findSurroundings(thePair, thread, &prevPair, &succPair, &prevInThread, &succInThread);
  107.  
  108.     /* Find the previous pair with the same name in the correct thread */
  109.     return(selfLookUp(prevInThread, string));
  110. }
  111.  
  112.  
  113. /* rebindContext(): starting from a pair, check the bindings of names
  114.  
  115.     Each property should refer to the previous defined property with the
  116.     same name in its context.
  117.     
  118.     This operation should be invoked when properties are CUT/COPY/PASTED
  119.     to/from an object. 'Oldcontext' must contain the original (unmodified)
  120.     context of the object.
  121. */
  122. void rebindContext(fromPair, oldContext)
  123. PAIR* fromPair;
  124. CONTEXT* oldContext;
  125. {
  126.   CONTEXT* thisContext = fromPair->cfa;
  127.   PAIR* thisPair = fromPair;
  128.     
  129.   oldProps = createList();
  130.   newProps = createList();
  131.   
  132.     /* Walk through all the properties starting from 'fromPair' */
  133.     while (thisPair) {
  134.         OBJECT* thisObject = thisPair->ofa;
  135.         STORE*    store = thisObject->mfa;
  136.         int     size  = thisObject->sfa;
  137.         OBJECT* newObject = NIL;
  138.         int     offset;
  139.  
  140.         /* printf("Checking '%s'.\n", thisPair->nfa); */
  141.         
  142.         /* Walk through all the slots in the current property */
  143.         for (offset = 0; offset < size; offset++) {
  144.             OBJECT* refObject = (OBJECT*)*((int*)store + offset);
  145.             PAIR*   origPair = NIL;
  146.             PAIR*    prevPair = NIL;
  147.             int     index;
  148.  
  149.             /* Check if binding must be updated */
  150.  
  151.             /* Case 1: A new intervening property with the same name */
  152.             /*         has been added between this and old pair? */ 
  153.             origPair = findNameInThis(thisContext, refObject);
  154.             if (origPair) {
  155.                 /* printf("  Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
  156.  
  157.                 prevPair = traverseThread(thisPair, origPair->nfa);
  158.                 if (prevPair && prevPair != origPair) {
  159.                     /* A new name has been added between the original and this pair */
  160.                     /* -> rebind to 'prevPair' */
  161.                     /* printf("   Rebinding reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
  162.                     rebind(&newObject, thisObject, offset, prevPair->ofa);                
  163.                 }
  164.             }
  165.  
  166.             /* Case 2: Try to bind the property using the same name that the property */
  167.             /*         had in its old context (context from which the property was */
  168.             /*         copied/pasted) */
  169.             else {
  170.                 if (oldContext) {
  171.                     /* Get the name to which the reference should be bound */
  172.                     origPair = findNameInThis(oldContext, refObject);
  173.                     if (origPair) {
  174.                         /* printf("  *Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
  175.  
  176.                         /* Using the name, find the possible corresponding property in new ctxt */
  177.                         prevPair = traverseThread(thisPair, origPair->nfa);
  178.                         if (prevPair) {
  179.                             /* Rebind the reference to 'prevPair' */
  180.                             /* printf("  *Rebinding a reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
  181.                             rebind(&newObject, thisObject, offset, prevPair->ofa);                        
  182.                         }
  183.                         else {
  184.                             fprintf(confile, "== Cannot rebind early bound call to '%s' in method '%s' ==\n", 
  185.                                 origPair->nfa, thisPair->nfa);
  186.                         }
  187.                     }
  188.                 }
  189.             }
  190.  
  191.             /* Case 3: The referred property has been redefined as a result of previous changes */
  192.             if (!prevPair && (index = findInList(oldProps, refObject))) {
  193.                 /* printf("Propagating a change.\n"); */
  194.                 rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
  195.             }
  196.         }
  197.  
  198.         /* If the property was changed, change the pair to refer to it */
  199.         if (newObject) {
  200.             thisPair->ofa = newObject;
  201.             fprintf(confile, "   Method '%s' recompiled.\n", thisPair->nfa);
  202.         }
  203.         thisPair = thisPair->sfa;
  204.     }
  205.  
  206.     deleteList(oldProps);
  207.     deleteList(newProps);
  208.     /* printf("Checking complete.\n"); */
  209. }    
  210.  
  211.